#include <iostream>
#include <vector>
#include <string>
#include <unordered_set>
#include <unordered_map>
using namespace std;

// 01_抽象思想
namespace _01_abstruct
{
    // 形状
    class Shape
    {
    public:
        virtual void Draw() = 0;
        virtual ~Shape() {}
    };

    // 矩形
    class Rect : public Shape
    {
    public:
        virtual void Draw()
        {
            cout << "Draw a rect!" << endl;
        }
    };

    // 圆形
    class Circle : public Shape
    {
    public:
        virtual void Draw()
        {
            cout << "Draw a circle!" << endl;
        }
    };

    // 线段
    class Line : public Shape
    {
    public:
        virtual void Draw()
        {
            cout << "Draw a line!" << endl;
        }
    };

    // 主窗口
    class MainForm
    {
    public:
        vector<Shape *> shapes;

        // 添加形状
        void Append(Shape *shape)
        {
            shapes.push_back(shape);
        }

        // 打印形状
        void Print()
        {
            for (auto elem : shapes)
            {
                elem->Draw();
            }
        }

        // 析构释放
        ~MainForm()
        {
            for (auto &elem : shapes)
            {
                delete elem;
                elem = nullptr;
            }
        }
    };

    void Test()
    {
        MainForm mf;
        mf.Append(new Rect);
        mf.Append(new Circle);
        mf.Append(new Line);
        mf.Print();
    }
}

// 02_模板方法模式
namespace _02_TemplateMethod
{
    // 程序库
    class Lib
    {
    public:
        void Run(int count)
        {
            Step1();

            if (Step2())
                Step3();

            for (int i = 0; i < count; ++i)
                Step4();

            Step5();
        }

        virtual ~Lib() {}

    protected:
        void Step1() { cout << "Step1()" << endl; }

        void Step3() { cout << "Step3()" << endl; }

        void Step5() { cout << "Step5()" << endl; }

        virtual bool Step2() = 0; // 变化

        virtual void Step4() = 0; // 变化
    };

    // 应用程序(依赖程序库)
    class App : public Lib
    {
    protected:
        virtual bool Step2() override
        {
            cout << "Step2()" << endl;
            return true;
        }

        virtual void Step4() override { cout << "Step4()" << endl; }
    };

    void Test()
    {
        Lib *p = new App;
        p->Run(5);
    }
}

// 03_策略模式
namespace _03_Strategy
{
    // 税率策略基类
    class TaxStrategy
    {
    public:
        virtual double Calculate(const string &context) = 0;
        virtual ~TaxStrategy() {}
    };

    class CN_Tax : public TaxStrategy
    {
    public:
        virtual double Calculate(const string &context)
        {
            return atof(context.c_str()) * 0.13;
        }
    };

    class US_Tax : public TaxStrategy
    {
    public:
        virtual double Calculate(const string &context)
        {
            return atof(context.c_str()) * 0.09;
        }
    };

    class JP_Tax : public TaxStrategy
    {
    public:
        virtual double Calculate(const string &context)
        {
            return atof(context.c_str()) * 0.15;
        }
    };

    class SalesOrder
    {
    private:
        TaxStrategy *strategy; // 多态成员变量

    public:
        SalesOrder(TaxStrategy *&&strategy) : strategy(strategy) {}

        ~SalesOrder() { delete strategy; }

        double CalculateTax(const string &context)
        {
            return strategy->Calculate(context);
        }
    };

    void Test()
    {
        SalesOrder order1(new CN_Tax);
        SalesOrder order2(new US_Tax);
        SalesOrder order3(new JP_Tax);
        cout << order1.CalculateTax("180.5") << endl;
        cout << order2.CalculateTax("180.5") << endl;
        cout << order3.CalculateTax("180.5") << endl;
    }
}

// 04_观察者模式
namespace _04_Observer
{
    // 通知控件接口
    class IProgress
    {
    public:
        virtual void DoProgress(float val) = 0;
        virtual ~IProgress() {}
    };

    // 文件分割器
    class FileSplitter
    {
    public:
        FileSplitter(const string &fileTxt, int fileNumber) : fileTxt(fileTxt), fileNumber(fileNumber) {}

        FileSplitter &Attach(IProgress *progress)
        {
            iProgressSet.insert(progress);
            return *this;
        }

        FileSplitter &Remove(IProgress *progress)
        {
            iProgressSet.erase(progress);
            return *this;
        }

        // 切分文件
        void Split()
        {
            // 1. 读取大文件
            cout << "Reading \"" << fileTxt << "\"" << endl;

            // 2. 分批次写入小文件
            for (int i = 0; i < fileNumber; ++i)
            {
                // 更新进度条
                for (auto iter = iProgressSet.begin(); iter != iProgressSet.end(); ++iter)
                {
                    float val = (float)(i + 1) / fileNumber;
                    (*iter)->DoProgress(val);
                }
            }
        }

    private:
        string fileTxt;                          // 文件名
        int fileNumber;                          // 文件数
        unordered_set<IProgress *> iProgressSet; // 多个观察者
    };

    // 文本框
    class TextBox
    {
    public:
        TextBox(const string &txt) : txt(txt) {}

        string GetTxt() { return txt; }

    private:
        string txt;
    };

    // 多观察者
    class AnotherObserver : public IProgress
    {
    public:
        virtual void DoProgress(float val) override
        {
            cout << "Another : " << val << endl;
        }
    };
    AnotherObserver obs;

    // 程序窗口
    class MainForm : public IProgress
    {
    public:
        MainForm(TextBox *&&txtFilePath, TextBox *&&txtFileNumber) : txtFileNumber(txtFileNumber), txtFilePath(txtFilePath) {}

        // 实现DoProgress
        virtual void DoProgress(float val) override
        {
            cout << "Progress Bar : " << val << endl;
        }

        // 按钮点击事件处理
        void OnButtonClicked()
        {
            string path = txtFilePath->GetTxt();
            int number = atoi(txtFileNumber->GetTxt().c_str());

            FileSplitter fs(path, number);
            fs.Attach(this).Attach(&obs);
            fs.Split();
        }

        ~MainForm()
        {
            delete txtFilePath;
            delete txtFileNumber;
        }

    private:
        TextBox *txtFilePath;   // 文件名文本框
        TextBox *txtFileNumber; // 文件数文本框
    };

    void Test()
    {
        MainForm form(new TextBox("file1.dll"), new TextBox("10"));
        form.OnButtonClicked();
    }
}

// 05_装饰模式
namespace _05_Decorator
{
    // 业务操作 流接口
    class IStream
    {
    public:
        virtual char Read(int num) = 0;

        virtual void Seek(int pos) = 0;

        virtual void Write(char data) = 0;

        virtual ~IStream() {}
    };

    // 文件流
    class FileStream : public IStream
    {
    public:
        virtual char Read(int num) override
        {
            cout << "File Read" << endl;
        }

        virtual void Seek(int pos) override
        {
            cout << "File Seek" << endl;
        }

        virtual void Write(char data) override
        {
            cout << "File Write" << endl;
        }
    };

    // 内存流
    class MemoryStream : public IStream
    {
    public:
        virtual char Read(int num) override
        {
            cout << "Memory Read" << endl;
        }

        virtual void Seek(int pos) override
        {
            cout << "Memory Seek" << endl;
        }

        virtual void Write(char data) override
        {
            cout << "Memory Write" << endl;
        }
    };

    // 网络流
    class NetworkStream : public IStream
    {
    public:
        virtual char Read(int num) override
        {
            cout << "Network Read" << endl;
        }

        virtual void Seek(int pos) override
        {
            cout << "Network Seek" << endl;
        }

        virtual void Write(char data) override
        {
            cout << "Network Write" << endl;
        }
    };

    // 扩展操作抽象类
    class DecoratorStream : public IStream
    {
    protected:
        IStream *stream;

    public:
        DecoratorStream(IStream *&&stream) : stream(stream) {}
    };

    // 加密扩展
    class CryptoStream : public DecoratorStream
    {
    private:
        void Crypto() { cout << "Crypto()" << endl; }

    public:
        CryptoStream(IStream *&&stream) : DecoratorStream(::move(stream)) {}

        virtual char Read(int num) override
        {
            stream->Read(num);
            Crypto();
        }

        virtual void Seek(int pos) override
        {
            stream->Seek(pos);
            Crypto();
        }

        virtual void Write(char data) override
        {
            stream->Write(data);
            Crypto();
        }
    };

    // 缓冲扩展
    class BufferStream : public DecoratorStream
    {
    private:
        void Buffer() { cout << "Buffer()" << endl; }

    public:
        BufferStream(IStream *&&stream) : DecoratorStream(::move(stream)) {}

        virtual char Read(int num) override
        {
            stream->Read(num);
            Buffer();
        }

        virtual void Seek(int pos) override
        {
            stream->Seek(pos);
            Buffer();
        }

        virtual void Write(char data) override
        {
            stream->Write(data);
            Buffer();
        }
    };

    void Test()
    {
        CryptoStream cs1(new FileStream);
        CryptoStream cs2(new MemoryStream);
        CryptoStream cs3(new NetworkStream);
        BufferStream bs(new CryptoStream(new FileStream));

        cs1.Read(1);
        cout << endl;
        cs2.Seek(2);
        cout << endl;
        cs3.Write('0');
        cout << endl;
        bs.Read(2);
    }
}

// 06_桥模式
namespace _06_Bridge
{
    class Image
    {
    };

    // 通信模块平台实现
    class IMessagerImp
    {
    public:
        virtual void PlaySound() = 0;
        virtual void DrawShape() = 0;
        virtual void WriteText() = 0;
        virtual void Connect() = 0;

        ~IMessagerImp() {}
    };

    // 通信模块接口
    class IMessager
    {
    public:
        virtual void Login(const string &username, const string &password) = 0;
        virtual void SendMessage(const string &message) = 0;
        virtual void SendPicture(const Image &image) = 0;

        IMessager(IMessagerImp *&&messager) : messager(messager) {}

        ~IMessager() {}

    protected:
        IMessagerImp *messager;
    };

    // PC通信模块
    class PCMessagerBase : public IMessagerImp
    {
    public:
        virtual void PlaySound() override
        {
            cout << "PC play sound" << endl;
        }

        virtual void DrawShape() override
        {
            cout << "PC draw shape" << endl;
        }

        virtual void WriteText() override
        {
            cout << "PC write text" << endl;
        }

        virtual void Connect() override
        {
            cout << "PC connect" << endl;
        }
    };

    // 移动通信模块
    class MobileMessagerBase : public IMessagerImp
    {
    public:
        virtual void PlaySound() override
        {
            cout << "Mobile play sound" << endl;
        }

        virtual void DrawShape() override
        {
            cout << "Mobile draw shape" << endl;
        }

        virtual void WriteText() override
        {
            cout << "Mobile write text" << endl;
        }

        virtual void Connect() override
        {
            cout << "Mobile connect" << endl;
        }
    };

    // 通信简化版本扩展
    class MessagerLite : public IMessager
    {
    public:
        MessagerLite(IMessagerImp *&&messager) : IMessager(::move(messager)) {}

        virtual void Login(const string &username, const string &password) override
        {
            messager->Connect();
        }

        virtual void SendMessage(const string &message) override
        {
            messager->WriteText();
        }

        virtual void SendPicture(const Image &image) override
        {
            messager->DrawShape();
        }
    };

    // 通信完整版本扩展
    class MessagerPerfect : public IMessager
    {
    public:
        MessagerPerfect(IMessagerImp *&&messager) : IMessager(::move(messager)) {}

        virtual void Login(const string &username, const string &password) override
        {
            messager->PlaySound();
            messager->Connect();
        }

        virtual void SendMessage(const string &message) override
        {
            messager->PlaySound();
            messager->WriteText();
        }

        virtual void SendPicture(const Image &image) override
        {
            messager->PlaySound();
            messager->DrawShape();
        }
    };

    void Test()
    {
        IMessager *m = new MessagerLite(new PCMessagerBase);
        m->Login("ASD", "123456");
        m->SendMessage("Hello");
        m->SendPicture(Image());
    }
}

// 07_工厂方法模式
namespace _07_Factory
{
    // 生产者接口
    class IProducer
    {
    public:
        virtual void Produce() = 0;

        virtual ~IProducer() {}
    };

    class FoodProducer : public IProducer
    {
    public:
        virtual void Produce() override
        {
            cout << "Produce food..." << endl;
        }
    };

    class ToyProducer : public IProducer
    {
    public:
        virtual void Produce() override
        {
            cout << "Produce toy..." << endl;
        }
    };

    // 抽象工厂
    class IProducerFactory
    {
    public:
        virtual IProducer *CreateProducer() = 0;

        virtual ~IProducerFactory() {}
    };

    // 具体工厂
    class FoodProducerFactory : public IProducerFactory
    {
    public:
        virtual IProducer *CreateProducer() override
        {
            return new FoodProducer;
        }
    };

    class ToyProducerFactory : public IProducerFactory
    {
    public:
        virtual IProducer *CreateProducer() override
        {
            return new ToyProducer;
        }
    };

    class Shop
    {
    public:
        Shop(IProducerFactory *&&factory) : factory(factory) {}

        void Sale()
        {
            // 生产
            IProducer *producer = factory->CreateProducer();
            producer->Produce();

            // 销售
            cout << "Saling..." << endl;
        }

    private:
        IProducerFactory *factory;
    };

    void Test()
    {
        Shop foodShop(new FoodProducerFactory);
        foodShop.Sale();
        Shop toyShop(new ToyProducerFactory);
        toyShop.Sale();
    }
}

// 08_抽象工厂模式
namespace _08_AbsractFactory
{
    class EmployeeDO
    {
    };

    // 抽象数据库链接
    class IDBConnection
    {
    public:
        virtual void Connect() = 0;

        virtual ~IDBConnection() {}
    };

    class SqlConnection : public IDBConnection
    {
    public:
        virtual void Connect() override
        {
            cout << "Sql connecting..." << endl;
        }
    };

    class OracleConnection : public IDBConnection
    {
    public:
        virtual void Connect() override
        {
            cout << "Oracle connecting..." << endl;
        }
    };

    // 抽象数据库命令
    class IDBCommand
    {
    public:
        virtual void Command() = 0;

        virtual ~IDBCommand() {}
    };

    class SqlCommand : public IDBCommand
    {
    public:
        virtual void Command() override
        {
            cout << "Sql command..." << endl;
        }
    };

    class OracleCommand : public IDBCommand
    {
    public:
        virtual void Command() override
        {
            cout << "Oracle command..." << endl;
        }
    };

    // 抽象工厂
    class IDBFactory
    {
    public:
        virtual IDBConnection *CreateDBConnection() = 0;

        virtual IDBCommand *CreateDBCommand() = 0;

        virtual ~IDBFactory() {}
    };

    class SqlFactory : public IDBFactory
    {
    public:
        virtual IDBCommand *CreateDBCommand() override
        {
            return new SqlCommand;
        }

        virtual IDBConnection *CreateDBConnection() override
        {
            return new SqlConnection;
        }
    };

    class OracleFactory : public IDBFactory
    {
    public:
        virtual IDBCommand *CreateDBCommand() override
        {
            return new OracleCommand;
        }

        virtual IDBConnection *CreateDBConnection() override
        {
            return new OracleConnection;
        }
    };

    // 员工数据库访问对象
    class EmployeeDAO
    {
    public:
        EmployeeDAO(IDBFactory *&&factory) : factory(factory) {}

        void GetEmployees()
        {
            IDBConnection *connection = factory->CreateDBConnection();
            connection->Connect();
            IDBCommand *command = factory->CreateDBCommand();
            command->Command();
        }

    private:
        IDBFactory *factory;
    };

    void Test()
    {
        EmployeeDAO edao1(new OracleFactory);
        edao1.GetEmployees();
        EmployeeDAO edao2(new SqlFactory);
        edao2.GetEmployees();
    }
}

// 09_原型模式
namespace _09_Prototype
{
    // 敌人接口（+工厂）
    class IEnemy
    {
    public:
        virtual IEnemy *Clone() = 0;

        virtual void Attack() = 0;
    };

    class Zombine : public IEnemy
    {
    public:
        Zombine() = default;
        Zombine(const Zombine &zombine) = default;

        virtual IEnemy *Clone() override
        {
            return new Zombine(*this);
        }

        virtual void Attack() override
        {
            cout << "Zombine is attacking!" << endl;
        }
    };

    class Beast : public IEnemy
    {
    public:
        Beast() = default;
        Beast(const Beast &beast) = default;

        virtual IEnemy *Clone() override
        {
            return new Beast(*this);
        }

        virtual void Attack() override
        {
            cout << "Beast is attacking!" << endl;
        }
    };

    // 场景
    class Scene
    {
    public:
        Scene(IEnemy *&&prototype) : prototype(prototype) {}

        void GenerateEnemy()
        {
            IEnemy *enemy = prototype->Clone();
            enemy->Attack();
        }

    private:
        IEnemy *prototype;
    };

    void Test()
    {
        Scene s(new Beast);
        s.GenerateEnemy();
    }
}

// 10_Builder
namespace _10_Builder
{
    class HouseDirctor;
    class IHouseBuilder
    {
        friend HouseDirctor;

    protected:
        virtual void Build1() = 0;
        virtual void Build2() = 0;
        virtual void Build3() = 0;
        virtual void Build4() = 0;
        virtual void Build5() = 0;
    };

    class StoneHouse : public IHouseBuilder
    {
    public:
        virtual void Build1() override { cout << "Stone Build1()" << endl; }
        virtual void Build2() override { cout << "Stone Build2()" << endl; }
        virtual void Build3() override { cout << "Stone Build3()" << endl; }
        virtual void Build4() override { cout << "Stone Build4()" << endl; }
        virtual void Build5() override { cout << "Stone Build5()" << endl; }
    };

    class HouseDirctor
    {
    public:
        HouseDirctor(IHouseBuilder *&&builder) : builder(builder) {}

        void Init()
        {
            builder->Build1();
            builder->Build2();
            builder->Build3();
            builder->Build4();
            builder->Build5();
        }

    private:
        IHouseBuilder *builder;
    };

    void Test()
    {
        HouseDirctor dirctor(new StoneHouse);
        dirctor.Init();
    }
}

// 11_单例模式
namespace _11_Singleton
{
    class Singleton
    {
    private:
        Singleton() { cout << "Singleton()" << endl; }
        Singleton(const Singleton &s) {}

    public:
        static Singleton *getInstance();
        static Singleton *instance;
    };

    Singleton *Singleton::instance = nullptr;

    // 线程不安全   懒汉式
    // Singleton* Singleton::getInstance()
    // {
    //     if (instance == nullptr)
    //         instance = new Singleton;
    //     return instance;
    // }

    class Lock
    {
    };

    // 线程安全    加锁代价过高    懒汉式
    // Singleton* Singleton::getInstance()
    // {
    //     Lock lock;
    //     if (instance == nullptr)
    //         instance = new Singleton;
    //     return instance;
    // }

    // 线程安全    双检查锁    内存读写出现reorder不安全
    Singleton *Singleton::getInstance()
    {
        if (instance != nullptr)
        {
            Lock lock;
            if (instance == nullptr)
                instance = new Singleton;
        }

        return instance;
    }

    void Test()
    {
        Singleton *object = Singleton::getInstance();
    }
}

// 12_享元模式
namespace _12_Flyweight
{
    class Bullet
    {
    private:
        string type;

    public:
        Bullet(const string& type) : type(type) {}

        void Damage() { cout << type << " Damaging..." << endl; }
    };

    class BulletFactory
    {
    private:
        unordered_map<string, Bullet*> pool;

        // 对象池工厂设计为单例模式
        BulletFactory() {} 
        BulletFactory(const BulletFactory& bf) {} 

    public:
        static BulletFactory* m_instance;

        static BulletFactory* GetInstance() { return m_instance; }

        Bullet* GetBullet(const string& type)
        {
            // 对象未创建过
            if (pool.find(type) == pool.end())
            {
                Bullet* b = new Bullet(type);
                pool.insert(make_pair(type, b));
                return b;
            }
            // 对象已创建
            else
                return pool[type];
        }
    };
    BulletFactory* BulletFactory::m_instance = new BulletFactory;

    void Test()
    {
        BulletFactory* bf = BulletFactory::GetInstance();
        auto b1 = bf->GetBullet("1.88mm");
        auto b2 = bf->GetBullet("7.92mm");
        auto b3 = bf->GetBullet("1.88mm");

        b1->Damage();
        b2->Damage();
        b3->Damage();
        printf("%p\n", b1);
        printf("%p\n", b3);
    }
}

// 13_门面模式
namespace _13_Facade
{
    class IHardware
    {
    public:
        virtual void Work() = 0;
    };

    class RAM : public IHardware
    {
    public:
        virtual void Work() override { cout << "RAM Work" << endl; }
    };

    class CPU : public IHardware
    {
    public:
        virtual void Work() override { cout << "CPU Work" << endl; }
    };

    class GPU : public IHardware
    {
    public:
        virtual void Work() override{ cout << "GPU Work" << endl; }
    };

    class Derive : public IHardware
    {
    public:
        virtual void Work() override { cout << "Derive Work" << endl; }
    };

    class OS
    {
    private:
        RAM* ram;
        CPU* cpu;
        GPU* gpu;
        Derive* derive;

    public:
        OS(RAM* &&ram, CPU* &&cpu, GPU* &&gpu, Derive* &&derive) :
            ram(ram), cpu(cpu), gpu(gpu), derive(derive) {}

        void ReadFile() 
        { 
            derive->Work();
            ram->Work();
            cpu->Work();
        }

        void Process() 
        { 
            ram->Work();
            cpu->Work();
        }

        void ShowImage() 
        { 
            gpu->Work();
        }
    };

    class User
    {
    private:
        OS* os;

    public:
        User() : os(new OS(new RAM, new CPU, new GPU, new Derive)) {}

        void Use()
        {
            os->Process();
            os->ReadFile();
            os->ShowImage();
        }
    };

    void Test()
    {
        User user;
        user.Use();
    }
}

// 14_代理模式
namespace _14_Proxy
{
    class ISubject
    {
    public:
        virtual void Process() = 0;
        virtual ~ISubject() { }
    };

    class RealSubject : public ISubject
    {
    public:
        virtual void Process() override
        {
            cout << "do something..." << endl;
        }
    };

    class Proxy : public ISubject
    {
    public:
        Proxy() : realSubject(new RealSubject) {}

        virtual void Process() override
        {
            cout << "proxy is protecting" << endl;
            realSubject->Process();
        }

    private:
        RealSubject* realSubject;
    };

    class ClientApp
    {
    public:
        ClientApp() : subject(new Proxy) {}

        void DoTask()
        {
            subject->Process();
        }

    private:
        ISubject* subject;
    };

    void Test()
    {
        ClientApp app;
        app.DoTask();
    }
}

int main(int argc, char **args)
{
    _14_Proxy::Test();
    return 0;
}